home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Graphics Programming (2nd Edition) / Visual Basic Graphics Programming 2nd Edition.iso / Src / Ch9 / Robot2.cls < prev    next >
Encoding:
Visual Basic class definition  |  1999-05-29  |  11.6 KB  |  368 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4.   Persistable = 0  'NotPersistable
  5.   DataBindingBehavior = 0  'vbNone
  6.   DataSourceBehavior  = 0  'vbNone
  7.   MTSTransactionMode  = 0  'NotAnMTSObject
  8. END
  9. Attribute VB_Name = "Robot"
  10. Attribute VB_GlobalNameSpace = False
  11. Attribute VB_Creatable = False
  12. Attribute VB_PredeclaredId = False
  13. Attribute VB_Exposed = False
  14. Option Explicit
  15.  
  16. ' Control point locations.
  17. Public Cx As Integer    ' Location of top of head.
  18. Public Cy As Integer
  19. Public LShoulderAngle As Single
  20. Public RShoulderAngle As Single
  21. Public LElbowAngle As Single
  22. Public RElbowAngle As Single
  23. Public LHipAngle As Single
  24. Public RHipAngle As Single
  25. Public LKneeAngle As Single
  26. Public RKneeAngle As Single
  27.  
  28. ' Dimensions.
  29. Public UpperArmLength As Single
  30. Public LowerArmLength As Single
  31. Public UpperLegLength As Single
  32. Public LowerLegLength As Single
  33. Public NeckLength As Single
  34. Public TrunkLength As Single
  35. Public BodyLength As Single
  36. Public HeadRadius As Single
  37.  
  38. ' Robot parts.
  39. Public Enum RobotPartEnum
  40.     part_Head
  41.     part_Lelbow
  42.     part_RElbow
  43.     part_LHand
  44.     part_RHand
  45.     part_LKnee
  46.     part_RKnee
  47.     part_LFoot
  48.     part_RFoot
  49.     part_Hips
  50.     part_Neck
  51.     part_Shoulders
  52.     part_MinPart = part_Head
  53.     part_MaxControlPart = part_RFoot
  54.     part_MaxPart = part_Shoulders
  55. End Enum
  56.  
  57. ' Grab handle distances.
  58. Public Enum GrabDistances
  59.     Near = 2
  60.     Near2 = 2 * Near
  61. End Enum
  62. ' Create a tween with parameters taken using
  63. ' fraction f1 of the first robot and (1 - f1)
  64. ' of the second.
  65. Public Sub Tween(ByVal f1 As Single, ByVal robot1 As Robot, ByVal robot2 As Robot)
  66. Dim f2 As Single
  67.  
  68.     f2 = 1# - f1
  69.     With robot1
  70.         Cx = f1 * .Cx + f2 * robot2.Cx
  71.         Cy = f1 * .Cy + f2 * robot2.Cy
  72.         LShoulderAngle = CombinedAngle(.LShoulderAngle, robot2.LShoulderAngle, f1, f2)
  73.         RShoulderAngle = CombinedAngle(.RShoulderAngle, robot2.RShoulderAngle, f1, f2)
  74.         LElbowAngle = CombinedAngle(.LElbowAngle, robot2.LElbowAngle, f1, f2)
  75.         RElbowAngle = CombinedAngle(.RElbowAngle, robot2.RElbowAngle, f1, f2)
  76.         LHipAngle = CombinedAngle(.LHipAngle, robot2.LHipAngle, f1, f2)
  77.         RHipAngle = CombinedAngle(.RHipAngle, robot2.RHipAngle, f1, f2)
  78.         LKneeAngle = CombinedAngle(.LKneeAngle, robot2.LKneeAngle, f1, f2)
  79.         RKneeAngle = CombinedAngle(.RKneeAngle, robot2.RKneeAngle, f1, f2)
  80.     End With
  81. End Sub
  82. ' Convert the angles so they differ by no more
  83. ' than PI. Then combine them using fraction f1
  84. ' of angle a1 and fraction f2 of a2.
  85. Private Function CombinedAngle(ByVal a1 As Single, ByVal a2 As Single, ByVal f1 As Single, ByVal f2 As Single) As Single
  86. Const PI = 3.14159265
  87. Const PI_TIMES_2 = PI * 2
  88.  
  89.     If Abs(a1 - a2) > PI Then
  90.         If a1 > a2 Then
  91.             Do
  92.                 a1 = a1 - PI_TIMES_2
  93.             Loop While a1 > a2
  94.         Else
  95.             Do
  96.                 a2 = a2 - PI_TIMES_2
  97.             Loop While a2 > a1
  98.         End If
  99.     End If
  100.  
  101.     CombinedAngle = f1 * a1 + f2 * a2
  102. End Function
  103. ' Copy another robot's parameters.
  104. Public Sub CopyFrame(from_me As Robot)
  105.     With from_me
  106.         Cx = .Cx
  107.         Cy = .Cy
  108.         LShoulderAngle = .LShoulderAngle
  109.         RShoulderAngle = .RShoulderAngle
  110.         LElbowAngle = .LElbowAngle
  111.         RElbowAngle = .RElbowAngle
  112.         LHipAngle = .LHipAngle
  113.         RHipAngle = .RHipAngle
  114.         LKneeAngle = .LKneeAngle
  115.         RKneeAngle = .RKneeAngle
  116.     End With
  117. End Sub
  118. ' Return the position of part of the robot.
  119. Public Sub Position(part As Integer, x As Integer, y As Integer)
  120.     Select Case part
  121.         Case part_Head
  122.             x = Cx
  123.             y = Cy
  124.         Case part_Neck
  125.             x = Cx
  126.             y = Cy + 2 * HeadRadius
  127.         Case part_Shoulders
  128.             x = Cx
  129.             y = Cy + 2 * HeadRadius + NeckLength
  130.         Case part_Lelbow
  131.             x = Cx + _
  132.                 UpperArmLength * Cos(LShoulderAngle)
  133.             y = Cy + 2 * HeadRadius + NeckLength - _
  134.                 UpperArmLength * Sin(LShoulderAngle)
  135.         Case part_RElbow
  136.             x = Cx + _
  137.                 UpperArmLength * Cos(RShoulderAngle)
  138.             y = Cy + 2 * HeadRadius + NeckLength - _
  139.                 UpperArmLength * Sin(RShoulderAngle)
  140.         Case part_LHand
  141.             x = Cx + _
  142.                 UpperArmLength * Cos(LShoulderAngle) + _
  143.                 LowerArmLength * Cos(LElbowAngle)
  144.             y = Cy + 2 * HeadRadius + NeckLength - _
  145.                 UpperArmLength * Sin(LShoulderAngle) - _
  146.                 LowerArmLength * Sin(LElbowAngle)
  147.         Case part_RHand
  148.             x = Cx + _
  149.                 UpperArmLength * Cos(RShoulderAngle) + _
  150.                 LowerArmLength * Cos(RElbowAngle)
  151.             y = Cy + 2 * HeadRadius + NeckLength - _
  152.                 UpperArmLength * Sin(RShoulderAngle) - _
  153.                 LowerArmLength * Sin(RElbowAngle)
  154.         Case part_Hips
  155.             x = Cx
  156.             y = Cy + 2 * HeadRadius + BodyLength
  157.         Case part_LKnee
  158.             x = Cx + _
  159.                 UpperLegLength * Cos(LHipAngle)
  160.             y = Cy + 2 * HeadRadius + BodyLength - _
  161.                 UpperLegLength * Sin(LHipAngle)
  162.         Case part_RKnee
  163.             x = Cx + _
  164.                 UpperLegLength * Cos(RHipAngle)
  165.             y = Cy + 2 * HeadRadius + BodyLength - _
  166.                 UpperLegLength * Sin(RHipAngle)
  167.         Case part_LFoot
  168.             x = Cx + _
  169.                 UpperLegLength * Cos(LHipAngle) + _
  170.                 LowerLegLength * Cos(LKneeAngle)
  171.             y = Cy + 2 * HeadRadius + BodyLength - _
  172.                 UpperLegLength * Sin(LHipAngle) - _
  173.                 LowerLegLength * Sin(LKneeAngle)
  174.         Case part_RFoot
  175.             x = Cx + _
  176.                 UpperLegLength * Cos(RHipAngle) + _
  177.                 LowerLegLength * Cos(RKneeAngle)
  178.             y = Cy + 2 * HeadRadius + BodyLength - _
  179.                 UpperLegLength * Sin(RHipAngle) - _
  180.                 LowerLegLength * Sin(RKneeAngle)
  181.     End Select
  182. End Sub
  183.  
  184.  
  185.  
  186. ' Draw the robot.
  187. Public Sub Draw(pic As PictureBox, handles As Boolean)
  188. Dim x1 As Integer
  189. Dim y1 As Integer
  190. Dim x2 As Integer
  191. Dim y2 As Integer
  192. Dim x3 As Integer
  193. Dim y3 As Integer
  194.  
  195.     ' Draw the head.
  196.     x1 = Cx
  197.     y1 = Cy + HeadRadius
  198.     pic.Circle (x1, y1), HeadRadius
  199.     If handles Then _
  200.         pic.Line (Cx - Near, Cy - Near)- _
  201.                 Step(Near2, Near2), , BF
  202.  
  203.     ' Draw the body.
  204.     y1 = y1 + HeadRadius
  205.     pic.Line (x1, y1)-Step(0, BodyLength)
  206.     
  207.     ' Draw the left arm.
  208.     y1 = y1 + NeckLength
  209.     x2 = x1 + UpperArmLength * Cos(LShoulderAngle)
  210.     y2 = y1 - UpperArmLength * Sin(LShoulderAngle)
  211.     pic.Line (x1, y1)-(x2, y2)
  212.     x3 = x2 + LowerArmLength * Cos(LElbowAngle)
  213.     y3 = y2 - LowerArmLength * Sin(LElbowAngle)
  214.     pic.Line -(x3, y3)
  215.     If handles Then _
  216.         pic.Line (x2 - Near, y2 - Near)- _
  217.                 Step(Near2, Near2), , BF
  218.     If handles Then _
  219.         pic.Line (x3 - Near, y3 - Near)- _
  220.                 Step(Near2, Near2), , BF
  221.  
  222.     ' Draw the right arm.
  223.     x2 = x1 + UpperArmLength * Cos(RShoulderAngle)
  224.     y2 = y1 - UpperArmLength * Sin(RShoulderAngle)
  225.     pic.Line (x1, y1)-(x2, y2)
  226.     x3 = x2 + LowerArmLength * Cos(RElbowAngle)
  227.     y3 = y2 - LowerArmLength * Sin(RElbowAngle)
  228.     pic.Line -(x3, y3)
  229.     If handles Then _
  230.         pic.Line (x2 - Near, y2 - Near)- _
  231.                 Step(Near2, Near2), , BF
  232.     If handles Then _
  233.         pic.Line (x3 - Near, y3 - Near)- _
  234.                 Step(Near2, Near2), , BF
  235.  
  236.     ' Draw the left leg.
  237.     y1 = y1 + TrunkLength
  238.     x2 = x1 + UpperLegLength * Cos(LHipAngle)
  239.     y2 = y1 - UpperLegLength * Sin(LHipAngle)
  240.     pic.Line (x1, y1)-(x2, y2)
  241.     x3 = x2 + LowerLegLength * Cos(LKneeAngle)
  242.     y3 = y2 - LowerLegLength * Sin(LKneeAngle)
  243.     pic.Line -(x3, y3)
  244.     If handles Then _
  245.         pic.Line (x2 - Near, y2 - Near)- _
  246.                 Step(Near2, Near2), , BF
  247.     If handles Then _
  248.         pic.Line (x3 - Near, y3 - Near)- _
  249.                 Step(Near2, Near2), , BF
  250.  
  251.     ' Draw the right leg.
  252.     x2 = x1 + UpperLegLength * Cos(RHipAngle)
  253.     y2 = y1 - UpperLegLength * Sin(RHipAngle)
  254.     pic.Line (x1, y1)-(x2, y2)
  255.     x3 = x2 + LowerLegLength * Cos(RKneeAngle)
  256.     y3 = y2 - LowerLegLength * Sin(RKneeAngle)
  257.     pic.Line -(x3, y3)
  258.     If handles Then _
  259.         pic.Line (x2 - Near, y2 - Near)- _
  260.                 Step(Near2, Near2), , BF
  261.     If handles Then _
  262.         pic.Line (x3 - Near, y3 - Near)- _
  263.                 Step(Near2, Near2), , BF
  264. End Sub
  265.  
  266.  
  267.  
  268. ' Move the control point to this location.
  269. Public Sub MoveControlPoint(part As Integer, Ax As Integer, Ay As Integer, x As Integer, y As Integer)
  270.     Select Case part
  271.         Case part_Head
  272.             Cx = x
  273.             Cy = y
  274.         Case part_Lelbow
  275.             LShoulderAngle = Arctan2(x - Ax, Ay - y)
  276.         Case part_RElbow
  277.             RShoulderAngle = Arctan2(x - Ax, Ay - y)
  278.         Case part_LHand
  279.             LElbowAngle = Arctan2(x - Ax, Ay - y)
  280.         Case part_RHand
  281.             RElbowAngle = Arctan2(x - Ax, Ay - y)
  282.         Case part_LKnee
  283.             LHipAngle = Arctan2(x - Ax, Ay - y)
  284.         Case part_RKnee
  285.             RHipAngle = Arctan2(x - Ax, Ay - y)
  286.         Case part_LFoot
  287.             LKneeAngle = Arctan2(x - Ax, Ay - y)
  288.         Case part_RFoot
  289.             RKneeAngle = Arctan2(x - Ax, Ay - y)
  290.     End Select
  291. End Sub
  292.  
  293. ' Initialize the robot's parameters.
  294. Public Sub SetParameters(x As Integer, y As Integer, ls As Single, rs As Single, le As Single, re As Single, lh As Single, rh As Single, lk As Single, rk As Single)
  295. Const PI = 3.14159265
  296. Const DEG_TO_RAD = PI / 180#
  297.  
  298.     Cx = x
  299.     Cy = y
  300.     LShoulderAngle = ls * DEG_TO_RAD
  301.     RShoulderAngle = rs * DEG_TO_RAD
  302.     LElbowAngle = le * DEG_TO_RAD
  303.     RElbowAngle = re * DEG_TO_RAD
  304.     LHipAngle = lh * DEG_TO_RAD
  305.     RHipAngle = rh * DEG_TO_RAD
  306.     LKneeAngle = lk * DEG_TO_RAD
  307.     RKneeAngle = rk * DEG_TO_RAD
  308. End Sub
  309.  
  310. ' Return the distance between the top of the head
  311. ' and the top of the robot when its height is as
  312. ' large as possible.
  313. Property Get HeadRoom()
  314.     HeadRoom = (UpperArmLength + LowerArmLength) - _
  315.         (2 * HeadRadius + NeckLength)
  316. End Property
  317. ' Return the maximum possible height the robot
  318. ' can have.
  319. Property Get MaxHeight()
  320.     MaxHeight = TrunkLength + UpperArmLength + LowerArmLength + _
  321.                 UpperLegLength + LowerLegLength
  322. End Property
  323.  
  324. ' Return the maximum possible width the robot
  325. ' can have.
  326. Property Get MaxWidth()
  327.     MaxWidth = 2 * (UpperArmLength + LowerArmLength)
  328. End Property
  329.  
  330.  
  331. ' Read the configuration data from a file.
  332. Sub FileInput(fnum)
  333.     Input #fnum, Cx, Cy, _
  334.         LShoulderAngle, RShoulderAngle, _
  335.         LElbowAngle, RElbowAngle, _
  336.         LHipAngle, RHipAngle, _
  337.         LKneeAngle, RKneeAngle, _
  338.         UpperArmLength, LowerArmLength, _
  339.         UpperLegLength, LowerLegLength, _
  340.         NeckLength, TrunkLength, _
  341.         BodyLength, HeadRadius
  342. End Sub
  343. ' Write the configuration data to a file.
  344. Sub FileWrite(fnum)
  345.     Write #fnum, Cx, Cy, _
  346.         LShoulderAngle, RShoulderAngle, _
  347.         LElbowAngle, RElbowAngle, _
  348.         LHipAngle, RHipAngle, _
  349.         LKneeAngle, RKneeAngle, _
  350.         UpperArmLength, LowerArmLength, _
  351.         UpperLegLength, LowerLegLength, _
  352.         NeckLength, TrunkLength, _
  353.         BodyLength, HeadRadius
  354. End Sub
  355. ' Set default dimensions.
  356. Private Sub Class_Initialize()
  357.     UpperArmLength = 40
  358.     LowerArmLength = 40
  359.     UpperLegLength = 40
  360.     LowerLegLength = 40
  361.     NeckLength = 10
  362.     TrunkLength = UpperArmLength * 1.1
  363.     BodyLength = NeckLength + TrunkLength
  364.     HeadRadius = (UpperArmLength - NeckLength) / 2
  365. End Sub
  366.  
  367.  
  368.